package br.com.felix.fwt.svg;

import java.io.PrintWriter;
import java.util.List;
import java.util.Stack;

import br.com.felix.fwt.svg.SVGStyle.TextAnchor;
import br.com.felix.fwt.svg.clipping.SVGClipPath;
import br.com.felix.fwt.svg.shapes.SVGRectangle;
import br.com.felix.fwt.svg.text.SVGText;

public class SVGBuilder {

	
	private Stack<String> editingElement;
	private PrintWriter pw;
	private StringBuilder strb;
	private Appender appender;
	
	private abstract class Appender{
		public abstract Appender append(String string);
		public abstract Appender append(int num) ;
		public abstract Appender append(float num) ;
		public abstract Appender append(Object obj) ;
	}
	
	
	
	private class PrintWriterAppender extends Appender{
		private PrintWriter pw;
		public PrintWriterAppender(PrintWriter pw){
			this.pw = pw;
		}
		@Override
		public Appender append(String string) {
			pw.write(string);
			return this;
		}

		@Override
		public Appender append(int num) {
			pw.write(String.valueOf(num));
			return this;
		}

		@Override
		public Appender append(float num) {
			pw.write(String.valueOf(num));
			return this;
		}

		@Override
		public Appender append(Object obj) {
			pw.write(obj.toString());
			return this;
		}
		
	}
	
	
	
	private class StringBuilderAppender extends Appender{
		private StringBuilder strb;
		public StringBuilderAppender(StringBuilder strb){
			this.strb = strb;
		}
		@Override
		public Appender append(String string) {
			strb.append(string);
			return this;
		}

		@Override
		public Appender append(int num) {
			strb.append(num);
			return this;
		}

		@Override
		public Appender append(float num) {
			strb.append(num);
			return this;
		}

		@Override
		public Appender append(Object obj) {
			strb.append(obj);
			return this;
		}
	}

	public SVGBuilder() {
		strb = new StringBuilder();
		appender = new StringBuilderAppender(strb);
		editingElement = new Stack<String>();
	}



	public SVGBuilder(PrintWriter printWriter) {
		pw = printWriter;
		appender = new PrintWriterAppender(pw);
		editingElement = new Stack<String>();
	}



	public void declare(SVGViewBox viewBox, int width, int height) {
		appender.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>").append("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\"\n").append("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n").append(
				"<svg xmlns=\"http://www.w3.org/2000/svg\"\n").append("xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\"\n").append("width=\"").append(width).append("px\" height=\"").append(height).append("px\"\n");
		if(viewBox!=null){
			appender.append("viewBox=\"").append(viewBox).append("\"\n");
		}
		appender.append("zoomAndPan=\"disable\" >\n");
	}



	public void endDeclaration() {
		appender.append("</svg>");
	}



	public SVGBuilder createElement(String elementName) {
		editingElement.push(elementName);
		appender.append("<").append(elementName);
		return this;
	}



	public SVGBuilder endElement() {
		String elementName = editingElement.pop();
		appender.append("</").append(elementName).append(">\n");
		return this;
	}



	public SVGBuilder attribute(String attributeName, String attributeValue) {
		appender.append(" ").append(attributeName).append("=\"").append(attributeValue).append("\"");
		return this;
	}



	public SVGBuilder attribute(String attributeName, Object attributeValue) {
		if(attributeValue!=null){
			appender.append(" ").append(attributeName).append("=\"").append(attributeValue).append("\"");
		}
		return this;
	}



	public SVGBuilder attribute(String attributeName, int attributeValue) {
		appender.append(" ").append(attributeName).append("=\"").append(attributeValue).append("\"");
		return this;
	}



	public SVGBuilder attribute(String attributeName, float attributeValue) {
		appender.append(" ").append(attributeName).append("=\"").append(attributeValue).append("\"");
		return this;
	}



	public SVGBuilder body(String text) {
		appender.append(">").append(text);
		return this;
	}



	public SVGBuilder endElementNoBody() {
		editingElement.pop();
		appender.append("/>\n");
		return this;
	}



	public String toString() {
		return strb.toString();
	}



	public static void main(String args[]) {
		SVGDocument svgPanel = new SVGDocument();
		SVGStyle style = new SVGStyle();
		style.fill(SVGColor.BLACK).textAnchor(TextAnchor.MIDDLE);
		SVGText svgText = new SVGText();
		svgText.style(style).x(100).y(25).text("Hello World!");
		svgPanel.add(svgText);

		SVGRectangle rect1 = new SVGRectangle();
		rect1.x(10).y(5).width(20).height(20).fill(SVGColor.BLUE);

		SVGRectangle rect2 = new SVGRectangle();
		rect2.x(20).y(10).width(160).height(20).fill(SVGColor.GREEN).opacity(0.5f);

		SVGRectangle rect3 = new SVGRectangle();
		rect3.x(170).y(25).width(20).height(20).fill(SVGColor.BLUE);

		svgPanel.add(rect1, rect2, rect3);
		System.out.println(svgPanel.toString());
	}



	public SVGBuilder attribute(String attributeName, int[] attributeArray) {
		if (attributeArray != null) {
			appender.append(" ").append(attributeName).append("=\"");
			for (int i = 0; i < attributeArray.length; i++) {
				appender.append(attributeArray[i]);
				if (i != attributeArray.length - 1){
					appender.append(",");
				}
			}
			appender.append("\"");
		}
		return this;
	}



	public SVGBuilder bodyWithChildren(List<SVG> children) {
		appender.append(">\n");
		for (SVG child : children) {
			child.toSVG(this);
		}
		return this;
	}



	public SVGBuilder percentileAttribute(String attributeName, int attributeValue) {
		appender.append(" ").append(attributeName).append("=\"").append(attributeValue).append("\"");
		return this;
	}



	public SVGBuilder id(SVGId id) {
		return attribute("id", id);
	}



	public SVGBuilder x(int x) {
		return attribute("x", x);
	}



	public SVGBuilder y(int y) {
		return attribute("y", y);
	}



	public SVGBuilder width(int width) {
		return attribute("width", width);
	}



	public SVGBuilder height(int height) {
		return attribute("height", height);
	}



	public SVGBuilder xlinkHref(String xlinkHref) {
		return attribute("xlink:href", xlinkHref);
	}



	public SVGBuilder xlinkHref(SVGId id) {
		return attribute("xlink:href", id);
	}



	public SVGBuilder clipPath(SVGClipPath clipPath) {
		return attribute("clip-path", clipPath);
	}
}
